package com.vvv.designpattern.structuredpattern;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author vvv
 * @date 2023-11-13 18 35
 * discription JDK动态代理
 */
public class JDKProxy {
    public static void main(String[] args) {
        /**
         * 动态代理合理的避免了静态代理的那种方式，不用事先为要代理的类而构建好代理类。而是在运行时通过反射机制创建
         *
         * 1. 代理对象,不需要实现接口，但是目标对象要实现接口，否则不能用动态代理
         *
         * 2. 代理类所在包:java.lang.reflect.Proxy
         *
         * 3. JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是:
         *  static Object newProxylnstance(ClassLoader loader,Class<?>[]interfaces,InvocationHandler h )
         *
         */
        Subject2 realSubject2 = new RealSubject2();
        JDKProxy1 jdkProxy1 = new JDKProxy1(realSubject2);
        Subject2 instance = (Subject2) jdkProxy1.getInstance();
        instance.doSomething();
    }
}

class JDKProxy1 {
    private Object target;

    public JDKProxy1(Object target) {
        this.target = target;
    }

    /*
     * 1.classLoader loader :指定当前目标对象使用的类加载器，获取加载器的方法固定
     * 2.Class<?>[] interfaces:目标对象实现的接口类型，使用泛型方法确认类型
     * 3.InvocationHandler  :事情处理，执行目标对象的方法时，会触发事情处理器方法
     * */
    public Object getInstance(){
        // 返回的就是代理对象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 执行代理对象的方法
                System.out.println("动态代理开始");
                Object result = method.invoke(target,args);// 反射机制调用目标方法
                System.out.println("动态代理结束");

                return result;
            }
        });
    }
}

/**
 * 接口
 */
interface Subject2 {
    void doSomething();
}

/**
 * 被代理对象(即目标对象)
 */
class RealSubject2 implements Subject2 {
    @Override
    public void doSomething() {
        System.out.println("RealSubject is doing something...");
    }
}
